package com.homelock.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.homelock.common.config.LockInitParam;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import com.homelock.common.util.LockEncryptUtil;
import com.homelock.constants.OpmodeEnum;
import com.homelock.domain.LockTemporaryPwdPostForm;
import com.homelock.domain.UserUnlockPostForm;
import com.homelock.entity.HlDevInfo;
import com.homelock.entity.HlDevTemporaryPwd;
import com.homelock.entity.HlDevTemporaryPwdExample;
import com.homelock.mapper.HlDevTemporaryPwdMapper;
import com.homelock.vo.LockTemporaryPwdVo;
import com.pi.base.enumerate.record.RecordState;
import com.pi.base.exception.ServiceException;
import com.pi.base.util.lang.ByteUtil;
import com.pi.base.util.lang.LongUtil;
import com.pi.config.enumerate.PartnerConfig;
import com.pi.config.service.ConfigService;

@Service
public class LockTemporaryPwdService {
    
    private static final Logger logger = LoggerFactory.getLogger(LockTemporaryPwdService.class);

    private HlDevTemporaryPwdMapper devTemporaryPwdMapper;

    private HlDevUserUnlockService devUserUnlockService;

    private HlDevInfoService devInfoService;
    
    private ConfigService configService;
    @Autowired
    LockInitParam lockInitParam;

    @Autowired
    @Lazy
    public LockTemporaryPwdService(HlDevUserUnlockService devUserUnlockService,
            HlDevTemporaryPwdMapper devTemporaryPwdMapper, HlDevInfoService devInfoService) {
        Assert.notNull(devTemporaryPwdMapper, "临时密码服务服务为空");
        Assert.notNull(devUserUnlockService, "开锁方式服务服务为空");
        Assert.notNull(devInfoService, "门锁服务服务为空");
        this.devUserUnlockService = devUserUnlockService;
        this.devTemporaryPwdMapper = devTemporaryPwdMapper;
        this.devInfoService = devInfoService;
    }

    public List<LockTemporaryPwdVo> generateTemporaryPwd(Long devId, Long operateUserId) {
        // 校验(可以忽略--会走全局权限校验)
        List<LockTemporaryPwdVo> tlist = new ArrayList<LockTemporaryPwdVo>(3);
        for (int i = 0; i < 3; i++) {
            // 生成临时密码
            String password = RandomStringUtils.random(6, "1234567890");
            HlDevTemporaryPwd record = new HlDevTemporaryPwd();
            Date date = new Date();
            record.setUnlockId(0L);
            record.setPwd(password);
            record.setUsageLimit(1);
            record.setEffectiveScope((byte) 1);
            record.setVersion((long) 1);
            record.setCreateDate(date);
            record.setUpdateDate(date);
            record.setState(true);
            // 保存临时密码到DevTemporaryPwd和HlDevUserUnlock表, 并设置开锁方式的状态为待确认
            devTemporaryPwdMapper.insertSelective(record);

            UserUnlockPostForm userUnlockPostForm = new UserUnlockPostForm();
            userUnlockPostForm.setDevId(devId);
            userUnlockPostForm.setUserId(operateUserId);
            userUnlockPostForm.setUnlockId(StringUtils.EMPTY);
            userUnlockPostForm.setOpmode(OpmodeEnum.UNLOCK_TPWD.getOpmode() & 0xFF);
            Long opmodeId = devUserUnlockService.addUserUnlock(userUnlockPostForm);

            LockTemporaryPwdVo pwdv = new LockTemporaryPwdVo();
            pwdv.setPwd(password);
            pwdv.setOpmodeId(opmodeId);
            tlist.add(pwdv);
        }
        // 返回封装结果
        return tlist;
    }

    public void confirmRecordPassword(List<LockTemporaryPwdPostForm> passwords) {
        // 校验
        if (CollectionUtils.isEmpty(passwords)) {
            return;
        }
        for (LockTemporaryPwdPostForm pwd : passwords) {
            // 更新临时密码的编号
            devUserUnlockService.updateUserUnlockId(pwd.getOpmodeId(), pwd.getUnlockId(), OpmodeEnum.UNLOCK_TPWD);
            // 更新HlDevUserUnlock表的phase状态为已确认(2)
            devUserUnlockService.updateUserUnlockPhase(pwd.getOpmodeId(), OpmodeEnum.UNLOCK_TPWD, 2);
        }
    }

    public void clearByTempPwdIds(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return;
        }
        HlDevTemporaryPwdExample example = new HlDevTemporaryPwdExample();
        example.createCriteria().andUnlockIdIn(ids);
        HlDevTemporaryPwd record = new HlDevTemporaryPwd();
        record.setState(RecordState.STATE_DELETE.getState());
        devTemporaryPwdMapper.updateByExampleSelective(record, example);
    }

    public String getOneTimePassword(Long devId) {
        HlDevInfo devInfo = devInfoService.getDevInfobyId(devId);
        byte[] lockId = ByteUtil.hexToByte(devInfo.getDevCode());
        Long time = devInfo.getCreateDate().getTime()/1000;
        byte[] lockIdentity;
        try {
            lockIdentity = LockEncryptUtil.getDevIdentity(lockId, devInfo.getRegCode(), time);
      //      byte[] encrypt = LockEncryptUtil.getCiperedDevIdentity(lockIdentity);
            byte[] encrypt = LockEncryptUtil.getCiperedDevIdentity(lockIdentity,lockInitParam.getSecretkeyByte());

            System.out.println(ByteUtil.byteToHex(lockIdentity));
            System.out.println(ByteUtil.byteToHex(encrypt));
            return LockEncryptUtil.getOneTimePassword(devInfo.getDevCode(),
                    ByteUtil.byte2UnsignedInt(encrypt), System.currentTimeMillis() / 1000);
        } catch (Exception e) {
            logger.error("", e);
            throw new ServiceException("获取一次性密码失败");
        }
    }
    
    public String getOneTimePasswordByAdmin(Long devId, Integer adminPwd) {
        HlDevInfo devInfo = devInfoService.getDevInfobyId(devId);
        String partnerConfig = configService.queryPartnerConfig(devInfo.getSourceId(), PartnerConfig.PARTNER_OTP_TABLE);
        byte[] otpTableBytes = Base64.decodeBase64(partnerConfig);
        long[] otpTable = LongUtil.byte2Long(otpTableBytes, 8);
        return LockEncryptUtil.getOneTimePassword(adminPwd, System.currentTimeMillis() / 1000, otpTable);
    }
    
   public static void main(String[] args) {
      System.out.println(LockEncryptUtil.getOneTimePassword("3BDE5E0BA63D97",
               ByteUtil.hexToUnsignedInt("c44e33cffca13883b7ac2e52224cf1a5"), 1570855147L));

   }
}
